package com.lj.back.manage.scaffold.module.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lj.back.manage.scaffold.common.util.Assert;
import com.lj.back.manage.scaffold.common.util.CommonUtil;
import com.lj.back.manage.scaffold.common.util.QueryWrapperUtil;
import com.lj.back.manage.scaffold.module.sys.DO.SysMenuDO;
import com.lj.back.manage.scaffold.module.sys.DTO.SysMenuDTO;
import com.lj.back.manage.scaffold.module.sys.DTO.SysMenuPageQuery;
import com.lj.back.manage.scaffold.module.sys.dao.SysMenuDao;
import com.lj.back.manage.scaffold.module.sys.service.SysMenuService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 后台管理---菜单service实现类
 * @author lv
 * @version 1.0.0
 */
@Service
@AllArgsConstructor
public class SysMenuServiceImpl implements SysMenuService {

    private final SysMenuDao sysMenuDao;

    private QueryWrapper<SysMenuDO> getBaseQueryWrapper(){
        QueryWrapper<SysMenuDO> queryWrapper = new QueryWrapper<>();
        return queryWrapper;
    }

    @Override
    public Set<SysMenuDTO> listMenuByRole(Long roleId) {
        Set<SysMenuDO> menuDOS;
        if (roleId == null){
            menuDOS = new HashSet<>(sysMenuDao.selectList(QueryWrapperUtil.getOrderByDescQueryWrapper()));
        }else {
            menuDOS = sysMenuDao.selectMenuByRole(roleId);
        }
        if (CollectionUtil.isEmpty(menuDOS)){
            return null;
        }
        Set<SysMenuDTO> menuDTOS = menuDOS.stream().map(sysMenuDO ->
                BeanUtil.copyProperties(sysMenuDO, SysMenuDTO.class)).collect(Collectors.toSet());
        return menuDTOS;
    }

    @Override
    public IPage<SysMenuDTO> listMenus(SysMenuPageQuery pageQuery){
        QueryWrapper<SysMenuDO> queryWrapper = QueryWrapperUtil.getPageQueryWrapper(SysMenuDO.class, pageQuery,"name","url");
        queryWrapper.eq(pageQuery.getType() != null,"type",pageQuery.getType());
        Page<SysMenuDO> page = sysMenuDao.selectPage(QueryWrapperUtil.getPage(pageQuery), queryWrapper);
        IPage<SysMenuDTO> sysMenuDTOPage = CommonUtil.pageBeanConvert(page, SysMenuDTO.class);
        return sysMenuDTOPage;
    }

    @Override
    public LinkedHashSet<SysMenuDTO> listMenus(){
        List<SysMenuDO> sysMenuDOS = sysMenuDao.selectList(QueryWrapperUtil.getOrderByDescQueryWrapper());
        if (CollectionUtil.isEmpty(sysMenuDOS)){
            return null;
        }
        return sysMenuDOS.stream()
                .map(sysMenuDO -> BeanUtil.copyProperties(sysMenuDO,SysMenuDTO.class))
                .collect(Collectors.toCollection(LinkedHashSet::new));
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public Long addMenu(SysMenuDTO menu){
        SysMenuDO sysMenuDO = BeanUtil.copyProperties(menu, SysMenuDO.class);
        sysMenuDao.insert(sysMenuDO);
        Set<Long> permIds = menu.getPermIds();
        if (CollectionUtil.isNotEmpty(permIds)){
            sysMenuDao.replaceInto(sysMenuDO.getId(),permIds);
        }
        return sysMenuDO.getId();
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public boolean removeMenu(long id){
        //获取所有子级菜单
        Set<Long> childrenMenuIds = listChildrenMenuIds(id);
        childrenMenuIds = CollectionUtil.isEmpty(childrenMenuIds) ? new HashSet<>() : childrenMenuIds;
        childrenMenuIds.add(id);
        //删除角色菜单关联表
        sysMenuDao.deleteRoleMenuByMenuIds(childrenMenuIds);
        //删除角色权限关联表
        sysMenuDao.deleteMenuPermByMenuIds(childrenMenuIds);
        //删除菜单表
        sysMenuDao.deleteBatchIds(childrenMenuIds);
        return true;
    }

    private Set<Long> listChildrenMenuIds(@NotNull(message = "{menu.id.notnull}") long id,Set<Long>... menuIdArray) {
        Set<Long> menuIds;
        if (menuIdArray == null || menuIdArray.length<1){
            menuIds = new HashSet<>();
        }else {
            menuIds = menuIdArray[0];
        }
        QueryWrapper<SysMenuDO> queryWrapper = QueryWrapperUtil.getOrderByDescQueryWrapper();
        queryWrapper.eq("parent_id",id);
        List<SysMenuDO> sysMenuDOS = sysMenuDao.selectList(queryWrapper);
        if (CollectionUtil.isEmpty(sysMenuDOS)){
            return null;
        }
        Set<Long> childrenMenuIds = sysMenuDOS.stream().map(sysMenuDO -> sysMenuDO.getId()).collect(Collectors.toSet());
        menuIds.addAll(childrenMenuIds);
        childrenMenuIds.stream().forEach(menuId->{
            listChildrenMenuIds(menuId,menuIds);
        });
        return menuIds;
    }

    @Override
    public boolean updateMenu(SysMenuDTO menu){
        SysMenuDO sysMenuDO = BeanUtil.copyProperties(menu, SysMenuDO.class);
        sysMenuDao.updateById(sysMenuDO);
        return true;
    }

    @Override
    public SysMenuDTO getMenuInfo(long id){
        SysMenuDO sysMenuDO = sysMenuDao.selectById(id);
        Assert.assertNotNull(sysMenuDO,"菜单ID不存在");
        return BeanUtil.copyProperties(sysMenuDO, SysMenuDTO.class);
    }
}
